﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace KUMC.Neurology.SomatoTopo
{
    class Utility
    {
        /*
         * Serializer
         * */
        public static void BinarySerialize(string filename, Study study)
        {
            try
            {
                FileStream fileStream;
                fileStream = new FileStream(filename, FileMode.Create);
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(fileStream, study);
                fileStream.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static object BinaryDeserialize(string filename)
        {
            try
            {
                FileStream fileStream;
                fileStream = new FileStream(filename, FileMode.Open);
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                object obj = binaryFormatter.Deserialize(fileStream);
                fileStream.Close();
                return obj;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /*
         * Bitmap <-> array
         * */
        public static int[] Bitmap2Data(Bitmap bmp)
        {
            int[] result = new int[bmp.Width * bmp.Height];
            BitmapData bmpdata = bmp.LockBits
                (new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            Marshal.Copy(bmpdata.Scan0, result, 0, bmp.Width * bmp.Height);
            bmp.UnlockBits(bmpdata);

            return result;
        }
        public static Bitmap Data2Bitmap(int[] data, int width, int height)
        {
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            BitmapData bmpData = bmp.LockBits
                (new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
            Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
            bmp.UnlockBits(bmpData);

            return bmp;
        }

        /* 
         * Color Scaling
         * */
        public static void Array2Bitmap(int[] source, ref Bitmap dest, float min, float max)
        {
            //Color[] cmap = GetRainbowColor();
            Color[] cmap = GetRedColor();

            float scale = max - min;
            float itv = scale / (cmap.Length-1);

            for (int i = 0; i < dest.Height; i++)
            {
                for (int j = 0; j < dest.Width; j++)
                {
                    float value = source[(i * dest.Width) + j];

                    if (value < min)
                    {
                        value = 0;
                    }
                    else if (value > max)
                    {
                        value = max;
                    }

                    if (value != 0)
                    {
                        float nv = ((value * (cmap.Length - 1)) - (min * (cmap.Length - 1))) / scale;
                        int idx = (int)nv;
                        dest.SetPixel(j, i, cmap[idx]);
                    }
                    else
                    {
                        dest.SetPixel(j, i, cmap[0]);
                    }

                }
            }            
        }

        public static Bitmap GetScaleBar(Color[] color)
        {
            Bitmap scalebar = new Bitmap(20, 100);

            for (int i = 0; i < scalebar.Size.Width; i++)
            {
                for (int j = 0; j < scalebar.Size.Height; j++)
                {
                    int idx = (color.Length * j) / scalebar.Size.Height;
                    scalebar.SetPixel(i, j, color[color.Length - idx - 1]);
                }
            }

            return scalebar;
        }
        public static Color[] GetRainbowColor()
        {
            Color[] color = new Color[64];

            color[1] = Color.FromArgb(255, 0, 0, 144);
            color[2] = Color.FromArgb(255, 0, 0, 160);
            color[3] = Color.FromArgb(255, 0, 0, 176);
            color[4] = Color.FromArgb(255, 0, 0, 192);
            color[5] = Color.FromArgb(255, 0, 0, 208);
            color[6] = Color.FromArgb(255, 0, 0, 224);
            color[7] = Color.FromArgb(255, 0, 0, 240);
            color[8] = Color.FromArgb(255, 0, 16, 255);
            color[9] = Color.FromArgb(255, 0, 32, 255);
            color[10] = Color.FromArgb(255, 0, 48, 255);
            color[11] = Color.FromArgb(255, 0, 64, 255);
            color[12] = Color.FromArgb(255, 0, 80, 255);
            color[13] = Color.FromArgb(255, 0, 96, 255);
            color[14] = Color.FromArgb(255, 0, 112, 255);
            color[15] = Color.FromArgb(255, 0, 128, 255);
            color[16] = Color.FromArgb(255, 0, 144, 255);
            color[17] = Color.FromArgb(255, 0, 160, 255);
            color[18] = Color.FromArgb(255, 0, 176, 255);
            color[19] = Color.FromArgb(255, 0, 192, 255);
            color[20] = Color.FromArgb(255, 0, 208, 255);
            color[21] = Color.FromArgb(255, 0, 224, 255);
            color[22] = Color.FromArgb(255, 0, 240, 255);
            color[23] = Color.FromArgb(255, 0, 255, 255);
            color[24] = Color.FromArgb(255, 16, 255, 240);
            color[25] = Color.FromArgb(255, 32, 255, 224);
            color[26] = Color.FromArgb(255, 48, 255, 208);
            color[27] = Color.FromArgb(255, 64, 255, 192);
            color[28] = Color.FromArgb(255, 80, 255, 176);
            color[29] = Color.FromArgb(255, 96, 255, 160);
            color[30] = Color.FromArgb(255, 112, 255, 144);
            color[31] = Color.FromArgb(255, 128, 255, 128);
            color[32] = Color.FromArgb(255, 144, 255, 112);
            color[33] = Color.FromArgb(255, 160, 255, 96);
            color[34] = Color.FromArgb(255, 176, 255, 80);
            color[35] = Color.FromArgb(255, 192, 255, 64);
            color[36] = Color.FromArgb(255, 208, 255, 48);
            color[37] = Color.FromArgb(255, 224, 255, 32);
            color[38] = Color.FromArgb(255, 240, 255, 16);
            color[39] = Color.FromArgb(255, 255, 255, 0);
            color[40] = Color.FromArgb(255, 255, 240, 0);
            color[41] = Color.FromArgb(255, 255, 224, 0);
            color[42] = Color.FromArgb(255, 255, 208, 0);
            color[43] = Color.FromArgb(255, 255, 192, 0);
            color[44] = Color.FromArgb(255, 255, 176, 0);
            color[45] = Color.FromArgb(255, 255, 160, 0);
            color[46] = Color.FromArgb(255, 255, 144, 0);
            color[47] = Color.FromArgb(255, 255, 128, 0);
            color[48] = Color.FromArgb(255, 255, 112, 0);
            color[49] = Color.FromArgb(255, 255, 96, 0);
            color[50] = Color.FromArgb(255, 255, 80, 0);
            color[51] = Color.FromArgb(255, 255, 64, 0);
            color[52] = Color.FromArgb(255, 255, 48, 0);
            color[53] = Color.FromArgb(255, 255, 32, 0);
            color[54] = Color.FromArgb(255, 255, 16, 0);
            color[55] = Color.FromArgb(255, 255, 0, 0);
            color[56] = Color.FromArgb(255, 240, 0, 0);
            color[57] = Color.FromArgb(255, 224, 0, 0);
            color[58] = Color.FromArgb(255, 208, 0, 0);
            color[59] = Color.FromArgb(255, 192, 0, 0);
            color[60] = Color.FromArgb(255, 176, 0, 0);
            color[61] = Color.FromArgb(255, 160, 0, 0);
            color[62] = Color.FromArgb(255, 144, 0, 0);
            color[63] = Color.FromArgb(255, 128, 0, 0);

            return color;
        }
        public static Color[] GetRedColor()
        {
            Color[] color = new Color[64];

            int itv = 4;
            int alp = 0;
            for (int i = 1; i < 64; i++)
            {
                color[i] = Color.FromArgb(alp, 255, 0, 0);
                alp += itv;
            }

            return color;
        }



        /*
         * In-Decoder
         * */
        public static int Incoding(int[] source)
        {
            int code = 0;

            for (int i = source.Length - 1; i >= 0; i--)
            {
                // index order : Alpha 5 4 3 2 1 0
                code = code + (source[i] << (i * 4));
            }

            return code;
        }
        public static int Decoding(int code, int filter)
        {
            int mask = 0xF;
            int result = (code >> (filter * 4)) & mask;            

            return result;
        }

    }
}
